﻿/********************************************************************
	日期:2022/4/30 9:44
	名称:DBMgr
	邮箱:yunnibbd@163.com
	作者:yunni
	描述:数据库管理类
*********************************************************************/

using MySql.Data.MySqlClient;
using PEProtocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

class DBMgr{
    private static DBMgr instance = null;

    public static DBMgr Instance{
        get{
            if (instance == null){
                instance = new DBMgr();
            }

            return instance;
        }
    }

    private MySqlConnection conn = null;

    public void Init(){
        // conn = new MySqlConnection(
        //     "server=192.168.137.33;port=3306;user=root;password=123456;database=darkgod;charset=utf8;");
        conn = new MySqlConnection(
            "server=gz-cdb-k5i9tln3.sql.tencentcdb.com;port=57724;user=root;password=yunnibbd@3111;database=darkgod;charset=utf8;");
        conn.Open();
        PECommon.Log("DBMgr Init done");
    }

    public PlayerData QueryPlayerData(string acct, string pass){
        PlayerData playerData = null;
        MySqlDataReader reader = null;
        bool isNew = true;
        try{
            MySqlCommand cmd = new MySqlCommand("select * from account where acct = @acct", conn);
            cmd.Parameters.AddWithValue("acct", acct);
            reader = cmd.ExecuteReader();
            if (reader.Read()){
                isNew = false;
                string _pass = reader.GetString("pass");
                if (_pass.Equals(pass)){
                    //密码正确，返回玩家数据
                    playerData = DBUtils.Pack<PlayerData>(reader);
                }

                //数据示意: 1#2#2#4

                #region 强化

                string[] strongStrArr = reader.GetString("strong").Split('#');
                int[] _strongArr = new int[6];
                for (int i = 0; i < strongStrArr.Length; i++){
                    if (strongStrArr[i] == ""){
                        continue;
                    }

                    if (int.TryParse(strongStrArr[i], out int starLv)){
                        _strongArr[i] = starLv;
                    }
                    else{
                        PECommon.Log("Parse Strong Data Error", LogType.Error);
                    }
                }

                playerData.strongArr = _strongArr;

                #endregion

                //1|0||0#1|0||0#1|0||0#1|0||0#

                #region task 任务

                //数据示意：1|1|0#2|1|0#3|1|0#4|1|0#5|1|0#6|1|0#
                string[] taskStrArr = reader.GetString("task").Split('#');
                playerData.taskArr = new string[6];
                for (int i = 0; i < taskStrArr.Length; i++){
                    if (taskStrArr[i] == ""){
                        continue;
                    }
                    else if (taskStrArr[i].Length >= 5){
                        playerData.taskArr[i] = taskStrArr[i];
                    }
                    else{
                        throw new Exception("DataError");
                    }
                }

                #endregion
            }
        }
        catch (Exception e){
            PECommon.Log("Query PlayerData By Acct&Pass Error:" + e, LogType.Error);
        }
        finally{
            if (reader != null){
                reader.Close();
            }

            if (isNew){
                //不存在账户数据，创建新的默认账号数据，并返回
                playerData = new PlayerData{
                    id = -1,
                    name = "",
                    level = 1,
                    exp = 0,
                    power = 150,
                    coin = 5000,
                    diamond = 500,
                    hp = 2000,
                    ad = 275,
                    ap = 265,
                    addef = 67,
                    apdef = 43,
                    dodge = 7,
                    pierce = 5,
                    critcal = 2,
                    guideid = 1001,
                    strongArr = new int[6],
                    crystal = 500,
                    time = TimerSvc.Instance.GetNowTime(),
                    taskArr = new string[6],
                    fuben = 10001,
                };
                
                //初始化任务奖励数据
                for (int i = 0; i < playerData.taskArr.Length; i++){
                    playerData.taskArr[i] = (i + 1) + "|0|0";
                }

                playerData.id = InsertNewAcctData(acct, pass, playerData);
            }
        }

        //TODO
        return playerData;
    }

    private int InsertNewAcctData(string acct, string pass, PlayerData playerData){
        int id = -1;
        try{
            MySqlCommand cmd = new MySqlCommand(
                "insert into account set acct=@acct,pass=@pass,name=@name,level=@level,exp=@exp,power=@power,coin=@coin,diamond=@diamond,crystal=@crystal," +
                "hp=@hp,ad=@ad,ap=@ap,addef=@addef,apdef=@apdef,dodge=@dodge,pierce=@pierce,critcal=@critcal,guideid=@guideid,strong=@strong,time=@time,task=@task,fuben=@fuben",
                conn);
            cmd.Parameters.AddWithValue("acct", acct);
            cmd.Parameters.AddWithValue("pass", pass);
            cmd.Parameters.AddWithValue("name", playerData.name);
            cmd.Parameters.AddWithValue("level", playerData.level);
            cmd.Parameters.AddWithValue("exp", playerData.exp);
            cmd.Parameters.AddWithValue("power", playerData.power);
            cmd.Parameters.AddWithValue("coin", playerData.coin);
            cmd.Parameters.AddWithValue("diamond", playerData.diamond);
            cmd.Parameters.AddWithValue("crystal", playerData.crystal);
            cmd.Parameters.AddWithValue("hp", playerData.hp);
            cmd.Parameters.AddWithValue("ad", playerData.ad);
            cmd.Parameters.AddWithValue("ap", playerData.ap);
            cmd.Parameters.AddWithValue("addef", playerData.addef);
            cmd.Parameters.AddWithValue("apdef", playerData.apdef);
            cmd.Parameters.AddWithValue("dodge", playerData.dodge);
            cmd.Parameters.AddWithValue("pierce", playerData.pierce);
            cmd.Parameters.AddWithValue("critcal", playerData.critcal);
            cmd.Parameters.AddWithValue("guideid", playerData.guideid);

            string strongInfo = "";
            for (int i = 0; i < playerData.strongArr.Length; i++){
                strongInfo += playerData.strongArr[i];
                strongInfo += "#";
            }

            cmd.Parameters.AddWithValue("strong", strongInfo);
            cmd.Parameters.AddWithValue("time", playerData.time);

            string taskInfo = "";
            for (int i = 0; i < playerData.taskArr.Length; i++){
                taskInfo += playerData.taskArr[i];
                taskInfo += "#";
            }
            cmd.Parameters.AddWithValue("task", taskInfo);
            cmd.Parameters.AddWithValue("fuben", playerData.fuben);

            //TOADD
            cmd.ExecuteNonQuery();
            id = (int) cmd.LastInsertedId;
        }
        catch (Exception e){
            PECommon.Log("Insert PlayerData Error:" + e, LogType.Error);
        }

        return id;
    }

    public bool QueryNameData(string name){
        bool exists = false;
        MySqlDataReader reader = null;
        try{
            MySqlCommand cmd = new MySqlCommand("select * from account where name = @name", conn);
            cmd.Parameters.AddWithValue("name", name);
            reader = cmd.ExecuteReader();
            if (reader.Read()){
                exists = true;
            }
        }
        catch (Exception e){
            PECommon.Log("Query Name State Error:" + e, LogType.Error);
        }
        finally{
            if (reader != null){
                reader.Close();
            }
        }

        return exists;
    }

    public bool UpdatePlayerData(int id, PlayerData playerData){
        try{
            MySqlCommand cmd =
                new MySqlCommand(
                    "update account set name=@name,level=@level,exp=@exp,power=@power,coin=@coin,diamond=@diamond,crystal=@crystal,hp=@hp,ad=@ad,ap=@ap,addef=@addef,apdef=@apdef,dodge=@dodge,pierce=@pierce,critcal=@critcal,guideid=@guideid,strong=@strong,time=@time,task=@task,fuben=@fuben where id = @id",
                    conn);
            cmd.Parameters.AddWithValue("id", id);
            cmd.Parameters.AddWithValue("name", playerData.name);
            cmd.Parameters.AddWithValue("level", playerData.level);
            cmd.Parameters.AddWithValue("exp", playerData.exp);
            cmd.Parameters.AddWithValue("power", playerData.power);
            cmd.Parameters.AddWithValue("coin", playerData.coin);
            cmd.Parameters.AddWithValue("diamond", playerData.diamond);
            cmd.Parameters.AddWithValue("crystal", playerData.crystal);
            cmd.Parameters.AddWithValue("hp", playerData.hp);
            cmd.Parameters.AddWithValue("ad", playerData.ad);
            cmd.Parameters.AddWithValue("ap", playerData.ap);
            cmd.Parameters.AddWithValue("addef", playerData.addef);
            cmd.Parameters.AddWithValue("apdef", playerData.apdef);
            cmd.Parameters.AddWithValue("dodge", playerData.dodge);
            cmd.Parameters.AddWithValue("pierce", playerData.pierce);
            cmd.Parameters.AddWithValue("critcal", playerData.critcal);
            cmd.Parameters.AddWithValue("guideid", playerData.guideid);

            string strongInfo = "";
            for (int i = 0; i < playerData.strongArr.Length; i++){
                strongInfo += playerData.strongArr[i];
                strongInfo += "#";
            }

            cmd.Parameters.AddWithValue("strong", strongInfo);
            cmd.Parameters.AddWithValue("time", playerData.time);
            
            string taskInfo = "";
            for (int i = 0; i < playerData.taskArr.Length; i++){
                taskInfo += playerData.taskArr[i];
                taskInfo += "#";
            }
            cmd.Parameters.AddWithValue("task", taskInfo);
            cmd.Parameters.AddWithValue("fuben", playerData.fuben);

            //TOADD Other
            cmd.ExecuteNonQuery();
        }
        catch (Exception e){
            PECommon.Log("Update PlayerData Error:" + e, LogType.Error);
            return false;
        }

        return true;
    }
}
